package puyu.manage.service.utils.except;

import io.lettuce.core.RedisCommandExecutionException;
import io.lettuce.core.RedisException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import puyu.manage.service.utils.CustomizeException;
import puyu.manage.service.utils.ErrorData;
import puyu.manage.service.utils.ExceptionConstant;
import puyu.manage.service.utils.R;

import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Arrays;
import java.util.List;


/**
 *  @ClassName: 全局异常处理器
 *  @author: whl
 *  @Date: 2024/5/27 15:31
 *  @Description: Description of this class
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {


    /**
     * 通用异常处理方法
     *
     * @return R
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R error(Exception e) {
        e.printStackTrace();

        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  e.getMessage() + "\n"+StringUtils.join(stackTraceElements.iterator(), "\n");

        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.OTHER_ERR_CODE)
                .mes1(ExceptionConstant.OTHER_ERR_MSG)
                .mse2(ExceptionConstant.ERROR_MES)
                .errmore(s).build();
        log.error(errorData.toString());
        return R.fail(ExceptionConstant.OTHER_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }

    /**
     * 空指针异常
     *
     * @return R
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public R error(NullPointerException e) {
        e.printStackTrace();

        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  StringUtils.join(stackTraceElements.iterator(), "\n");
        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.NullPointerException_ERR_CODE)
                .mes1(ExceptionConstant.NullPointerException_ERR_MES)
                .mse2(ExceptionConstant.ERROR_MES)
                .errmore(s).build();
        log.error(errorData.toString());

        return R.fail(ExceptionConstant.NullPointerException_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }

    /**
     * 算术运算异常
     *
     * @return R
     */
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public R error(ArithmeticException e) {
        e.printStackTrace();

        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  e.getMessage() + "\n"+StringUtils.join(stackTraceElements.iterator(), "\n");

        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.ArithmeticException_ERR_CODE)
                .mes1(ExceptionConstant.ArithmeticException_ERR_MES)
                .mse2(ExceptionConstant.ERROR_MES)
                .errmore(s).build();
        log.error(errorData.toString());

        return R.fail(ExceptionConstant.ArithmeticException_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }

    /**
     * 运行时未知异常
     *
     * @return R
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public R error(RuntimeException e) {
        e.printStackTrace();
        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  e.getMessage() + "\n"+StringUtils.join(stackTraceElements.iterator(), "\n");
        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.RuntimeException_ERR_CODE)
                .mes1(ExceptionConstant.RuntimeException_ERR_MES)
                .mse2(ExceptionConstant.ERROR_MES)
                .errmore(s).build();
        log.error(errorData.toString());

        return R.fail(ExceptionConstant.RuntimeException_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }

    /**
     * sql异常
     *
     * @return R
     */
    @ExceptionHandler({BadSqlGrammarException.class, SQLException.class})
    @ResponseBody
    public R errorSql(Exception e) {

        e.printStackTrace();

        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  e.getMessage() + "\n"+ StringUtils.join(stackTraceElements.iterator(), "\n");

        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.BadSqlGrammarException_ERR_CODE)
                .mes1(ExceptionConstant.BadSqlGrammarException_ERR_MES)
                .mse2(ExceptionConstant.ERROR_MES)
                .errmore(s).build();
        log.error(errorData.toString());

        return R.fail(ExceptionConstant.BadSqlGrammarException_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }

    /**
     * 数组越界异常
     *
     * @return R
     */
    @ExceptionHandler({IndexOutOfBoundsException.class})
    @ResponseBody
    public R errorSql(IndexOutOfBoundsException e) {

        e.printStackTrace();
        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.IndexOutOfBoundsException_ERR_CODE)
                .mes1(ExceptionConstant.IndexOutOfBoundsException_ERR_MES)
                .mse2(ExceptionConstant.ERROR_MES)
                .errmore(e.getMessage()).build();
        log.error(errorData.toString());

        return R.fail(ExceptionConstant.IndexOutOfBoundsException_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }


    /**
     * 自定义异常
     *
     * @return R
     */
    @ExceptionHandler(CustomizeException.class)
    @ResponseBody
    public R error(CustomizeException e) {
        e.printStackTrace();
        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  e.getMessage() + "\n"+ StringUtils.join(stackTraceElements.iterator(), "\n");

        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.BgtException_ERR_CODE)
                .mes1(e.getMessage())
                .mse2(e.getSystemMessage())
                .errmore(s).build();
        log.error(errorData.toString());

        return R.fail(ExceptionConstant.BgtException_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }

    /**
     * 违反唯一约束异常
     *
     * @return R
     */
    @ExceptionHandler(DataAccessException.class)
    @ResponseBody
    public R error(SQLIntegrityConstraintViolationException e) {
        e.printStackTrace();

        System.out.println("打印异常信息:"+e.getMessage());
        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  e.getMessage() + "\n"+StringUtils.join(stackTraceElements.iterator(), "\n");
        if(e.getMessage().contains("ORA-00001")){
            log.error(e.getMessage());

            return R.fail(ExceptionConstant.UniqueConstraintException_ERR_CODE, ExceptionConstant.ERROR_MSG, ErrorData.builder().errcode(ExceptionConstant.UniqueConstraintException_ERR_CODE)
                    .mes1(ExceptionConstant.UniqueConstraintException_ERR_MES)
                    .mse2(ExceptionConstant.UNIQUE_ERROR_MES)
                    .errmore(s).build());
        }else{
            log.error(e.getMessage());

            return R.fail(ExceptionConstant.RuntimeException_ERR_CODE, ExceptionConstant.ERROR_MSG, ErrorData.builder().errcode(ExceptionConstant.RuntimeException_ERR_CODE)
                    .mes1(ExceptionConstant.RuntimeException_ERR_MES)
                    .mse2(ExceptionConstant.ERROR_MES)
                    .errmore(s).build());
        }
    }

    /**
     * redis异常
     *
     * @return R
     */
    @ExceptionHandler(RedisException.class)
    @ResponseBody
    public R error(RedisException e) {
        e.printStackTrace();

        List<StackTraceElement> stackTraceElements = Arrays.asList(e.getStackTrace());
        String s =  e.getMessage() + "\n"+ StringUtils.join(stackTraceElements.iterator(), "\n");

        ErrorData errorData =ErrorData.builder().errcode(ExceptionConstant.BgtException_ERR_CODE)
                .mes1(e.getMessage())
                .errmore(s).build();
        log.error(errorData.toString());

        return R.fail(ExceptionConstant.BgtException_ERR_CODE, ExceptionConstant.ERROR_MSG, errorData);
    }

}
